#******************************************************************************
#
#
TARGET := freertos
ODIR ?= .build
OBJODIR := $(ODIR)/obj

# A simple variant is to prefix commands with $(Q) - that's useful
# for commands that shall be hidden in non-verbose mode.
#
#	$(Q)ln $@ :<
#
# To put more focus on warnings, be less verbose as default
# Use 'make V=1' to see the full commands
ifeq ("$(origin V)", "command line")
	BUILD_VERBOSE = $(V)
else
	BUILD_VERBOSE = 0
endif

ifeq ($(BUILD_VERBOSE),1)
	Q =
else
	Q = @
endif

# Do not print "Entering directory ...",
# but we want to display it when entering to the output directory
# so that IDEs/editors are able to understand relative filenames.
MAKEFLAGS += --no-print-directory

# Cross compiling and selecting different set of gcc/bin-utils
# ---------------------------------------------------------------------------
#
# CROSS_COMPILE specify the prefix used for all executables used
# during compilation. Only gcc and related bin-utils executables
# are prefixed with $(CROSS_COMPILE).
# CROSS_COMPILE can be set on the command line
# make CROSS_COMPILE=ia64-linux-
# Alternatively CROSS_COMPILE can be set in the environment.
# Default value for CROSS_COMPILE is arm-none-eabi-
CROSS_COMPILE ?=

# Make variables (CC, etc...)
AS		= $(CROSS_COMPILE)gcc
LD		= $(CROSS_COMPILE)g++
CC		= $(CROSS_COMPILE)gcc
CXX		= $(CROSS_COMPILE)g++
AR		= $(CROSS_COMPILE)ar
NM		= $(CROSS_COMPILE)nm
STRIP	= $(CROSS_COMPILE)strip
OBJCOPY	= $(CROSS_COMPILE)objcopy
OBJDUMP	= $(CROSS_COMPILE)objdump
SIZE	= $(CROSS_COMPILE)size

# File System Utilities
MKDIR	= mkdir -p
RM		= rm -f
MV		= mv -f

LDFILES	:=
LIBS	:= -lpthread
BIN2OBJ	:= -I binary -O elf32-littlearm -B arm --rename-section .data=.rodata

CPUFLAGS :=

COMMONFLAGS := \
	-g3 -O2 \
	-fmessage-length=0 \
	-ffunction-sections \
	-fdata-sections \
	-fsigned-char \
	-fsingle-precision-constant \
	-Wfloat-equal \
	-Wuninitialized \
	-Wextra \
	-Wall

CCFLAGS := \
	-std=gnu11

CPPFLAGS := \
	-std=c++1y \
	-fno-rtti \
	-fno-exceptions\
	-fpermissive \
	-fexceptions \
	-DCPP_FREERTOS_CONDITION_VARIABLES

LDFLAGS := \
	-Wl,-Map="$(ODIR)/$(TARGET).map" \
	-Wl,--gc-sections \
	-Wl,--print-memory-usage

COMPONENT_PATH = components/FreeRTOS
include $(COMPONENT_PATH)/component.mk

INCLUDES += $(COMPONENT_INCLUDES)

#******************************************************************************

#COMPONENTS_PATH
COMPONENTS_PATH = components

#FreeRTOS ADDONS
FREERTOS_ADDONS_PATH = $(COMPONENTS_PATH)/freertos-addons

#EasyLoger Lib
EASYLOGER_PATH = $(COMPONENTS_PATH)/EasyLogger/easylogger
EASYLOGER_PORT_PATH = $(COMPONENTS_PATH)/EasyLogger/demo/os/linux/easylogger

#UORB Lib
UORB_PATH = $(COMPONENTS_PATH)/uorb

#Main PATH
MAIN_PATH = main

# Header File
INCLUDES += -I ./
INCLUDES += -I$(COMPONENTS_PATH)
INCLUDES += -I$(FREERTOS_ADDONS_PATH)/source/include
INCLUDES += -I$(EASYLOGER_PORT_PATH)/inc  -I$(EASYLOGER_PORT_PATH)/plugins/ -I$(EASYLOGER_PATH)/plugins/ -I$(EASYLOGER_PATH)/inc
INCLUDES += -I$(UORB_PATH)/include -I$(UORB_PATH)
INCLUDES += -I$(UORB_PATH)/include -I$(UORB_PATH)/src
INCLUDES += -I$(MAIN_PATH)

#******************************************************************************
# C File
CSRCS += $(wildcard *.c)
CSRCS += $(wildcard $(COMPONENTS_PATH)/*.c)
CSRCS += $(wildcard $(EASYLOGER_PATH)/src/*.c)
CSRCS += $(wildcard $(EASYLOGER_PATH)/plugins/file/elog_file.c)
CSRCS += $(wildcard $(EASYLOGER_PORT_PATH)/port/*.c)
CSRCS += $(wildcard $(EASYLOGER_PORT_PATH)/plugins/file/*.c)
CSRCS += $(wildcard $(MAIN_PATH)/*.c)

#******************************************************************************
# CPP File
CPPSRCS += $(wildcard *.cpp)
CPPSRCS += $(wildcard $(FREERTOS_ADDONS_PATH)/source/*.cpp)
CPPSRCS += $(wildcard $(UORB_PATH)/src/*.cpp)
CPPSRCS += $(wildcard $(UORB_PATH)/src/base/*.cpp)
CPPSRCS += $(wildcard $(MAIN_PATH)/topics/*.cpp)
CPPSRCS += $(wildcard $(MAIN_PATH)/*.cpp)

#******************************************************************************
# ASM File (*.S)
ASRCS +=

#******************************************************************************
# ASM File (*.s)
ASRCs +=

#******************************************************************************
# Binary resource (*)
BSRC +=

COMPONENT_OBJS :=	$(CSRCS:%.c=$(OBJODIR)/%.o) \
		$(CPPSRCS:%.cpp=$(OBJODIR)/%.o) \
		$(ASRCs:%.s=$(OBJODIR)/%.o) \
		$(ASRCS:%.S=$(OBJODIR)/%.o) \
		$(BSRC:%=$(OBJODIR)/%)

DEPS :=	$(CSRCS:%.c=$(OBJODIR)/%.d) \
		$(CPPSRCS:%.cpp=$(OBJODIR)/%.d) \
		$(ASRCs:%.s=$(OBJODIR)/%.d) \
		$(ASRCS:%.S=$(OBJODIR)/%.d)

OBJS :=	$(CSRCS:%.c=$(OBJODIR)/%.o) \
		$(CPPSRCS:%.cpp=$(OBJODIR)/%.o) \
		$(ASRCs:%.s=$(OBJODIR)/%.o) \
		$(ASRCS:%.S=$(OBJODIR)/%.o) \
		$(BSRC:%=$(OBJODIR)/%)

DEPS :=	$(CSRCS:%.c=$(OBJODIR)/%.d) \
		$(CPPSRCS:%.cpp=$(OBJODIR)/%.d) \
		$(ASRCs:%.s=$(OBJODIR)/%.d) \
		$(ASRCS:%.S=$(OBJODIR)/%.d)

ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),disasm)
ifdef DEPS
sinclude $(DEPS)
endif
endif
endif

$(OBJODIR)/%.o: %.c
	@echo [CC] $<
	$(Q)$(MKDIR) $(dir $@)
	$(Q)$(CC) -MT $@ -MMD -MP -MF $(OBJODIR)/$*.Td 	$(CPUFLAGS) $(COMMONFLAGS) $(CCFLAGS) $(INCLUDES) -c -o $@ $<
	$(Q)$(MV) $(OBJODIR)/$*.Td $(OBJODIR)/$*.d && touch $@

$(OBJODIR)/%.o: %.cpp
	@echo [CXX] $<
	$(Q)$(MKDIR) $(dir $@)
	$(Q)$(CXX) -MT $@ -MMD -MP -MF $(OBJODIR)/$*.Td $(CPUFLAGS) $(COMMONFLAGS) $(CPPFLAGS) $(INCLUDES) -c -o $@ $<
	$(Q)$(MV) $(OBJODIR)/$*.Td $(OBJODIR)/$*.d && touch $@

$(OBJODIR)/%.o: %.s
	@echo [AS] $<
	$(Q)$(MKDIR) $(dir $@)
	$(Q)$(AS) $(CFLAGS) -M -o $(OBJODIR)/$*.d $<
	$(Q)$(AS) $(CFLAGS) -MMD -MP -MF $(OBJODIR)/$*.d -MT$@ -c -o $@ $<

$(OBJODIR)/%.o: %.S
	@echo [AS] $<
	$(Q)$(MKDIR) $(dir $@)
	$(Q)$(AS) $(CFLAGS) -M -o $(OBJODIR)/$*.d $<
	$(Q)$(AS) $(CFLAGS) -MMD -MP -MF $(OBJODIR)/$*.d -MT$@ -c -o $@ $<

$(OBJODIR)/%: %
	@echo [OBJCOPY] $<
	$(Q)$(MKDIR) $(dir $@)
	$(Q)$(OBJCOPY) $(BIN2OBJ) $< $@

#******************************************************************************
# Targets
#

OUTFILE_STR = generate $(ODIR)/$(TARGET).elf
FINISH_STR = [make all] [make app] [make clean] [make listc]

PHONY += all
all: $(OBJS)
	$(Q)$(LD) $(CPUFLAGS) $(LDFLAGS) $(LDFILES) $(OBJS) $(LIBS) -o $(ODIR)/$(TARGET).elf
	@echo $(CSRCS)
	@echo ' '
	@echo $(OBJS)
	@echo ' '
	@echo $(INCLUDES)
	@echo ' '
	@echo "\033[32m${OUTFILE_STR}\033[0m"
	@echo "\033[32m${FINISH_STR}\033[0m"

PHONY += app
app:
	@make all
	@echo "\n\n"
	@echo 'run FreeRTOS on Linux:'
	@./$(ODIR)/$(TARGET).elf

PHONY += clean
clean:
	$(Q)$(RM) -r -v $(ODIR)
	@echo 'clean finish'

PHONY += listc
listc:
	@echo $(CSRCS) $(CPPSRCS) $(CASRCS)

# Declare the contents of the .PHONY variable as phony.  We keep that
# information in a variable so we can use it in if_changed and friends.
.PHONY: $(PHONY)

# Set default target
.DEFAULT_GOAL:= all

